#include "serverresponseparser.h"
#include <QtXml>
#include <QIODevice>
#include <QDebug>
#include "noise.h"

ServerResponseParser::ServerResponseParser(QObject *parent) : QObject(parent){

}

void ServerResponseParser::parseXML(QIODevice *io){
    QString error;
    int line;
    int column;

    QDomDocument responseDocument;

    if(!responseDocument.setContent(io,true,&error,&line,&column)){
        qDebug()<<error<<" "<<line<<" "<<column;
        return;
    }

    QDomElement root = responseDocument.documentElement();

    if(root.tagName()=="login"){
        QDomElement resultValue = root.toElement();
        if(resultValue.text()=="OK")
            emit loginSucceeded();
        else if(resultValue.text()=="FAILED")
            emit loginFailed();
    }

    else if(root.tagName()=="logout"){
        QDomElement resultValue = root.toElement();
        if(resultValue.text()=="OK")
            emit logoutSucceeded();
        else if(resultValue.text()=="FAILED")
            emit logoutFailed();
    }

    else if(root.tagName()=="player_list"){
        QDomNode player = root.firstChild();
        QList<QString> players;

        while(!player.isNull()){
            players<<player.toElement().text().trimmed();
            player=player.nextSibling();
        }
        emit playersAvailable(players);
    }

    else if(root.tagName()=="challenge"){
        QDomElement resultValue = root.toElement();
        if(resultValue.text().trimmed()!="")
            emit challengedBy(resultValue.text());
        else
            emit noChallenges();
    }
    else if(root.tagName()=="challenge_status"){
        QDomElement resultValue = root.toElement();
        qDebug()<<"Status "<<resultValue.text();
        if(resultValue.text().trimmed()=="OK")
            emit challengeAccepted();
        else if(resultValue.text().trimmed()=="DECLINE")
            emit challengeDeclined();
    }

    else if(root.tagName()=="challenge_delivery"){
        QDomElement idElement = root.firstChild().toElement();
        QDomElement playerElement = root.firstChild().nextSibling().toElement();

        bool ok;

        QString player = playerElement.text().trimmed();
//      THIS MUST BE CHANGED TO SUPPORT A VERY ACTIVE SERVER
//      IT MIGHT BE PRONE TO BUGS IN CASE THAT THE ID IS GREATER THAN THE MAX_VALUE OF AN INTEGER
        int challengeId = idElement.text().toInt(&ok);
        emit challengeDelivered(challengeId,player);
    }

    else if(root.tagName()=="map"){
    bool ok;

    float width;
    float height;
    float movementSpeed;
    int falldownPenalty;
    float diffFactor;

    DrunkSceneModel *parsedModel=0;
    int stateUpdateInterval=0;
    int randomSeed=0;

    QDomNode gameplay=root.firstChild();
    QDomNode map=gameplay.nextSibling();
    QDomNode objects=map.nextSibling();

    if(gameplay.toElement().tagName()!="gameplay" && map.toElement().tagName()!="map" &&
            objects.toElement().tagName()!="object_list")
        return;

    QDomNode gameConfig=gameplay.firstChild();
    QDomNode mapConfig=map.firstChild();
    QDomNode object=objects.firstChild();

    while(!gameConfig.isNull()){
        QDomElement element=gameConfig.toElement();
        if(element.tagName()=="state_timer_interval_ms")
            stateUpdateInterval=element.text().toInt(&ok);
        else if(element.tagName()=="random_seed")
            randomSeed=element.text().toInt(&ok);

        gameConfig=gameConfig.nextSibling();
    }

    while(!mapConfig.isNull()){//get map configuration
        QDomElement element=mapConfig.toElement();
        if(element.tagName()=="width"){
            if(element.text()==""){
                parsedModel=0;
                stateUpdateInterval=-1;
                randomSeed=0;
                return;
            }

            else
                width=element.text().toDouble(&ok);

        }
        else if(element.tagName()=="height"){
            if(element.text()==""){
                parsedModel=0;
                stateUpdateInterval=-1;
                randomSeed=0;
                return;
            }
            else
                height=element.text().toDouble(&ok);
        }
        else if(element.tagName()=="movement_speed"){
            if(element.text()==""){
                parsedModel=0;
                stateUpdateInterval=-1;
                randomSeed=0;
                return;
            }
            else
                movementSpeed=element.text().toDouble(&ok);
        }
        else if(element.tagName()=="falldown_penalty_ms"){
            if(element.text()==""){
                parsedModel=0;
                stateUpdateInterval=-1;
                randomSeed=0;
                return;
            }
            else
                falldownPenalty=element.text().toInt(&ok);
        }
        else if(element.tagName()=="difficulty_factor"){
            if(element.text()==""){
                parsedModel=0;
                stateUpdateInterval=-1;
                randomSeed=0;
                return;
            }
            else
                diffFactor=element.text().toDouble(&ok);
        }
        mapConfig=mapConfig.nextSibling();
    }

    qDebug()<<stateUpdateInterval<<width<<height<<movementSpeed<<falldownPenalty;

    parsedModel=new DrunkSceneModel(stateUpdateInterval,width,height,new Noise(randomSeed),movementSpeed,falldownPenalty);
    parsedModel->setNavigationDifficulty(diffFactor);

    while(!object.isNull()){//get all objects
        QDomNode objectConfig=object.firstChild();

        QString resourceId;
        float xPos;
        float yPos;
        float objWidth;
        int effectDurationInMs;

        float gravityFactor;
        float randomnessFactor;
        float walkingSpeedFactor;

        while(!objectConfig.isNull()){
            QDomElement element=objectConfig.toElement();

            if(element.tagName()=="resource_id"){
                resourceId=element.text();
                qDebug()<<"Parsing Object "<<resourceId;
            }
            else if(element.tagName()=="x_position"){
                xPos=element.text().toDouble(&ok);
            }
            else if(element.tagName()=="y_position"){
                yPos=element.text().toDouble(&ok);
            }
            else if(element.tagName()=="object_width"){
                objWidth=element.text().toDouble(&ok);
            }
            else if(element.tagName()=="effect_duration_ms"){
                effectDurationInMs=element.text().toInt(&ok);
            }
            else if(element.tagName()=="gravity_factor"){
                gravityFactor=element.text().toDouble(&ok);
            }
            else if(element.tagName()=="randomness_factor"){
                randomnessFactor=element.text().toDouble(&ok);
            }
            else if(element.tagName()=="walking_speed_factor"){
                walkingSpeedFactor=element.text().toDouble(&ok);
            }
            objectConfig=objectConfig.nextSibling();
        }

        parsedModel->putObject(new SceneObject(gravityFactor,randomnessFactor,walkingSpeedFactor,
                                         effectDurationInMs,xPos,yPos,objWidth,resourceId));
        object=object.nextSibling();

}
    emit mapReady(parsedModel);
    }

    else if(root.tagName()=="accept_challenge"){
        QDomElement resultValue = root.toElement();
        if(resultValue.text().trimmed()=="OK")
            emit passiveChallengeMapReady();
    }

}
